#ifndef __UDT__PRIV_H__
#define __UDT__PRIV_H__

#ifdef __cplusplus
extern "C" {
#else
typedef int UDTSOCKET;

////////////////////////////////////////////////////////////////////////////////

enum EPOLLOpt
{
   // this values are defined same as linux epoll.h
   // so that if system values are used by mistake, they should have the same effect
   UDT_EPOLL_IN = 0x1,
   UDT_EPOLL_OUT = 0x4,
   UDT_EPOLL_ERR = 0x8
};

enum UDTSTATUS {INIT = 1, OPENED, LISTENING, CONNECTING, CONNECTED, BROKEN, CLOSING, CLOSED, NONEXIST};

enum UDTOpt
{
	UDT_MSS,             // the Maximum Transfer Unit
	UDT_SNDSYN,          // if sending is blocking
	UDT_RCVSYN,          // if receiving is blocking
	UDT_CC,              // custom congestion control algorithm
	UDT_FC,		// Flight flag size (window size)
	UDT_SNDBUF,          // maximum buffer in sending queue
	UDT_RCVBUF,          // UDT receiving buffer size
	UDT_LINGER,          // waiting for unsent data when closing
	UDP_SNDBUF,          // UDP sending buffer size
	UDP_RCVBUF,          // UDP receiving buffer size
	UDT_MAXMSG,          // maximum datagram message size
	UDT_MSGTTL,          // time-to-live of a datagram message
	UDT_RENDEZVOUS,      // rendezvous connection mode
	UDT_SNDTIMEO,        // send() timeout
	UDT_RCVTIMEO,        // recv() timeout
	UDT_REUSEADDR,	// reuse an existing port or create a new one
	UDT_MAXBW,		// maximum bandwidth (bytes per second) that the connection can use
	UDT_STATE,		// current socket state, see UDTSTATUS, read only
	UDT_EVENT,		// current avalable events associated with the socket
	UDT_SNDDATA,		// size of data in the sending buffer
	UDT_RCVDATA		// size of data available for recv
};

struct CPerfMon
{
   // global measurements
   int64_t msTimeStamp;                 // time since the UDT entity is started, in milliseconds
   int64_t pktSentTotal;                // total number of sent data packets, including retransmissions
   int64_t pktRecvTotal;                // total number of received packets
   int pktSndLossTotal;                 // total number of lost packets (sender side)
   int pktRcvLossTotal;                 // total number of lost packets (receiver side)
   int pktRetransTotal;                 // total number of retransmitted packets
   int pktSentACKTotal;                 // total number of sent ACK packets
   int pktRecvACKTotal;                 // total number of received ACK packets
   int pktSentNAKTotal;                 // total number of sent NAK packets
   int pktRecvNAKTotal;                 // total number of received NAK packets
   int64_t usSndDurationTotal;		// total time duration when UDT is sending data (idle time exclusive)

   // local measurements
   int64_t pktSent;                     // number of sent data packets, including retransmissions
   int64_t pktRecv;                     // number of received packets
   int pktSndLoss;                      // number of lost packets (sender side)
   int pktRcvLoss;                      // number of lost packets (receiver side)
   int pktRetrans;                      // number of retransmitted packets
   int pktSentACK;                      // number of sent ACK packets
   int pktRecvACK;                      // number of received ACK packets
   int pktSentNAK;                      // number of sent NAK packets
   int pktRecvNAK;                      // number of received NAK packets
   double mbpsSendRate;                 // sending rate in Mb/s
   double mbpsRecvRate;                 // receiving rate in Mb/s
   int64_t usSndDuration;		// busy sending time (i.e., idle time exclusive)

   // instant measurements
   double usPktSndPeriod;               // packet sending period, in microseconds
   int pktFlowWindow;                   // flow window size, in number of packets
   int pktCongestionWindow;             // congestion window size, in number of packets
   int pktFlightSize;                   // number of packets on flight
   double msRTT;                        // RTT, in milliseconds
   double mbpsBandwidth;                // estimated bandwidth, in Mb/s
   int byteAvailSndBuf;                 // available UDT sender buffer size
   int byteAvailRcvBuf;                 // available UDT receiver buffer size
};
#define P2P_UDT_ERRO -1
#define P2P_UDT_ECONNLOST 2001
#define P2P_UDT_EINVSOCK 5004
#endif

typedef enum UDTOpt SOCKOPT;
typedef struct CPerfMon TRACEINFO;
extern void udtp_startup(void);
extern void udtp_cleanup(void);
extern const char *udtp_geterromessage(void);
extern int udtp_geterrocode(void);
extern int udtp_socket(int af, int type, int protocol);
extern int udtp_getsockopt(UDTSOCKET u, int level,
		SOCKOPT optname, char* optval, int* optlen);
extern int udtp_setsockopt(UDTSOCKET u, int level,
		SOCKOPT optname, const char* optval, int optlen);
extern UDTSOCKET udtp_accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen);
extern int udtp_get_sock_by_udt(UDTSOCKET u);
extern int udtp_bind(UDTSOCKET u, struct sockaddr* name, int namelen);
extern int udtp_close(UDTSOCKET u);
extern int udtp_connect(UDTSOCKET u, const struct sockaddr* name, int namelen);
extern int udtp_getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen);
extern int udtp_getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen);
extern int udtp_listen(UDTSOCKET u,int backlog);
extern int udtp_perfmon(UDTSOCKET u, TRACEINFO* perf, int clear);
extern int udtp_recv(UDTSOCKET u, char* buf, int len, int flags);
extern int udtp_recvmsg(UDTSOCKET u, char* msg, int len);
extern void udtp_udclr(int fd, int rdflag);
extern int udtp_udisset(int fd, int rdflag);
extern void udtp_udset(int fd, int rdflag);
extern void udtp_udzero(int rdflag);
extern int udtp_select(int nfds, int rdflag, int wrflag,
		const struct timeval* timeout);
extern int udtp_send(UDTSOCKET u, const char* buf, int len, int flags);
extern int udtp_sendmsg(UDTSOCKET u, const char* msg, int len, int ttl, int inorder);

#ifdef __cplusplus
} //end if __cplusplus
#endif

#endif
